package auctionhaus

import grails.test.*

import com.auctionhaus.Customer
import com.auctionhaus.Bid
import com.auctionhaus.Listing


class BidTests  extends  GroovyTestCase {
    transient Date testDate =  new Date((2011-1900), 01, 15); //02-15-2011
    transient Date testFutureDate =  new Date(System.currentTimeMillis()+100);

    protected void setUp() {
        super.setUp()
        deleteAllFromDatabase()
    }

    protected void tearDown() {
        super.tearDown()
        deleteAllFromDatabase()

    }

    private void deleteAllFromDatabase() {

        Listing.findAll().each {x -> x.delete() }
        Customer.findAll().each {x -> x.delete() }
    }

    void testSomething() {

    }
    //B-1: Bids have the following required fields: amount and date/time of bid (integration test)
    void testBidsRequireAmountAndDate() {
        deleteAllFromDatabase()

        def customerSeller = new Customer (emailAddress: "original@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)
        def auctionListing = new Listing (listName:'Jeep Grand Cherokee',
                                                            description:'Shiny',
                                                            endDateTime: new Date(2011,3,1),
                                                            startBidPrice:100,
                                                            seller:customerSeller).save(failOnError:true)
        def buyer1 = new Customer (emailAddress: "buyer1@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)

        def badBidNoAmount = new Bid(buyer: buyer1, date:new Date(2011,3,4), listing:auctionListing)
        badBidNoAmount.validate()
        assertTrue 'This should not work!', badBidNoAmount.hasErrors()

        def badBidNoDate = new Bid(amount:501, buyer: buyer1, listing:auctionListing)
        badBidNoDate.validate()
        assertTrue 'This should not work!', badBidNoDate.hasErrors()


        def goodBid = new Bid(amount:502, buyer: buyer1, date:new Date(2011,3,4), listing:auctionListing)
        goodBid.validate()
        assertFalse 'This should work!', goodBid.hasErrors()

        def nextGoodBid = new Bid(amount:505, buyer: buyer1, date:new Date(2011,3,4), listing:auctionListing)
        nextGoodBid.validate()
        assertFalse 'This should work!', nextGoodBid.hasErrors()
    }
    //B-2: Bids are required to be for a Listing (integration test)
    void testBidsRequiredForAListing() {
        deleteAllFromDatabase()

        def customerSeller = new Customer (emailAddress: "original@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)
        def auctionListing = new Listing (listName:'Jeep Grand Cherokee',
                                                            description:'Shiny',
                                                            endDateTime: new Date(2011,3,1),
                                                            startBidPrice:100,
                                                            seller:customerSeller).save(failOnError:true)
        def buyer1 = new Customer (emailAddress: "buyer1@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)

        def myBadBid = new Bid(amount:4000, buyer: buyer1, date:new Date(2011,3,4))
        assertFalse 'This should not work!', myBadBid.validate()

        def myBid = new Bid(amount:4000, buyer: buyer1, date:new Date(2011,3,4), listing:auctionListing)
        assertTrue 'This should work!', myBid.validate()
    }

    void testFindHighestBid()
    {
        deleteAllFromDatabase()

        //Get all the bids for a listing
        def customerSeller = new Customer (emailAddress: "original@gmail.com", password: "abcdefg", date:new Date()).save()
        def auctionListing = new Listing (listName:'Jeep Grand Cherokee',
                                            description:'Shiny',
                                            endDateTime:new Date(2011,3,1),
                                            startBidPrice:1,
                                            seller:customerSeller)
        def buyerInstance = new Customer (emailAddress: "buyer@gmail.com", password: "abcdefg", date:new Date()).save()
        def myBid = new Bid(amount:4001, buyer:buyerInstance, date:new Date(2011,3,4))

        def buyerInstanceX = new Customer (emailAddress: "whatever3@gmail.com", password: "abcdefg", date:new Date()).save()
        def myBidX = new Bid(amount:5000, buyer:buyerInstanceX, date:new Date(2011,3,4))

        def buyerInstanceY = new Customer (emailAddress: "whatever4@gmail.com", password: "abcdefg", date:new Date()).save()
        def myBidY = new Bid(amount:6000, buyer:buyerInstanceY, date:new Date(2011,3,4))

        def buyerInstanceZ = new Customer (emailAddress: "whatever5@gmail.com", password: "abcdefg", date:new Date()).save()
        def myBidZ = new Bid(amount:7000, buyer:buyerInstanceZ, date:new Date(2011,3,4))

        auctionListing.addToBids(myBid)
        auctionListing.addToBids(myBidX)
        auctionListing.addToBids(myBidY)
        auctionListing.addToBids(myBidZ)

        auctionListing.save()

        if (!auctionListing)
            auctionListing = Listing.findByListName('Jeep Grand Cherokee')
         def bids = Bid.findAllByListing(auctionListing)
        assertEquals bids.size(), 4
        //Get the highest bid
         assertEquals 7000, auctionListing.getMaxBidPrice()
    }

    //B-3: Bids are required to have a bidder (Customer) (integration test)
    void testBidsRequireBidder(){
        deleteAllFromDatabase()

        def customerSeller = new Customer (emailAddress: "original@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)
        def auctionListing = new Listing (listName:'Jeep Grand Cherokee',
                                                            description:'Shiny',
                                                            endDateTime: new Date(2011,3,1),
                                                            startBidPrice:100,
                                                            seller:customerSeller).save(failOnError:true)
        def buyer1 = new Customer (emailAddress: "buyer1@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)

        //no bidder/buyer
        def myBid = new Bid(amount:4000, date:new Date(2011,3,4), listing:auctionListing)
        assertFalse 'This should not work!', myBid.validate()


        def herBid = new Bid(amount:4000, buyer: buyer1, date:new Date(2011,3,4), listing:auctionListing)
        assertTrue 'This should work!', herBid.validate()

    }

    // B-4: A Listing has a list of Bids for that Listing (integration test)
    void testListingHasBidsForThatListing(){
        deleteAllFromDatabase()

        def customerSeller = new Customer (emailAddress: "original@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)
        def buyer1 = new Customer (emailAddress: "buyer1@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)
        def buyer2 = new Customer (emailAddress: "buyer2@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)

       //auction listing created...and saved.
        def auctionListing = new Listing (listName:'Jeep Grand Cherokee',
                                                            description:'Shiny',
                                                            endDateTime: new Date(2011,3,1),
                                                            startBidPrice:100,
                                                            seller:customerSeller).save(failOnError:true)
        def secondListing = new Listing (listName:'Jeep Wrangler',
                                                            description:'Rugged',
                                                            endDateTime: new Date(2011,3,1),
                                                            startBidPrice:150,
                                                            seller:customerSeller).save(failOnError:true)

        //bids added to auctionListing.
         def myBid1 = new Bid(amount:101, buyer:buyer1, date:new Date(2011,3,4), listing:auctionListing).save()
         def myBid2 = new Bid(amount:102, buyer:buyer2, date:new Date(2011,3,4), listing:auctionListing).save()
         def myBid3 = new Bid(amount:103, buyer:buyer2, date:new Date(2011,3,4), listing:auctionListing).save()

        def foundBids = Bid.findAllByListing(auctionListing)
        assertEquals foundBids.size(), 3


        def myBid4 = new Bid(amount:155, buyer:buyer1, date:new Date(2011,3,4), listing:secondListing).save()
        def myBid5 = new Bid(amount:156, buyer:buyer2, date:new Date(2011,3,4), listing:secondListing).save()
        def myBid6 = new Bid(amount:157, buyer:buyer2, date:new Date(2011,3,4), listing:secondListing).save()
        def myBid7 = new Bid(amount:158, buyer:buyer2, date:new Date(2011,3,4), listing:secondListing).save()

        def foundSecondBids = Bid.findAllByListing(secondListing)
        assertEquals foundSecondBids.size(), 4

    }

    // B-5: The Bid amount must be at least .50 higher than the previous Bid for the same item (integration test)
    void testValidateBidRate()
    {
        deleteAllFromDatabase()

        //Get all the bids for a listing
        def customerSeller = new Customer (emailAddress: "original@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)
        def auctionListing = new Listing (listName:'Jeep Grand Cherokee',
                                            description:'Shiny',
                                            endDateTime: new Date(2011,3,1),
                                            startBidPrice:100,
                                            seller:customerSeller)
        def buyerInstance = new Customer (emailAddress: "buyer@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)
        def buyerInstanceX = new Customer (emailAddress: "whatever3@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)

        def myBid = new Bid(amount:140, buyer:buyerInstance, date:new Date(2011,3,4))
        def myBidX = new Bid(amount:140.60, buyer:buyerInstanceX, date:new Date(2011,3,4))

        auctionListing.addToBids(myBid)
        auctionListing.addToBids(myBidX)
        auctionListing.save()

        def foundAuctionByListing = Listing.findByListName('Jeep Grand Cherokee')
        assertEquals foundAuctionByListing.bids.size(), 2

        def foundBids = Bid.findAllByListing(foundAuctionByListing)
        assertEquals foundBids.size(), 2

        // Counter bid
        def badBid = new Bid(amount:140.70, buyer:buyerInstance, date:new Date(2011,3,4))
        foundAuctionByListing.addToBids(badBid);
        foundAuctionByListing.save()
        foundAuctionByListing = Listing.findByListName('Jeep Grand Cherokee')

        foundBids = Bid.findAllByListing(foundAuctionByListing)
        assertEquals foundBids.size(), 2


    }
    //B-6: When a Listing is saved, any new Bids added for the listing must be saved (integration test)
    void testListingUpdatesMustSaveNewBids(){
        deleteAllFromDatabase()

        def customerSeller = new Customer (emailAddress: "original@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)
        def buyer1 = new Customer (emailAddress: "buyer1@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)
        def buyer2 = new Customer (emailAddress: "buyer2@gmail.com", password: "abcdefg", date:new Date()).save(failOnError:true)

       //auction listing created...and saved.
        def auctionListing = new Listing (listName:'Jeep Grand Cherokee',
                                                            description:'Shiny',
                                                            endDateTime: new Date(2011,3,1),
                                                            startBidPrice:100,
                                                            seller:customerSeller)

        //bids added to auctionListing.
         def myBid1 = new Bid(amount:140, buyer:buyer1, date:new Date(2011,3,4))
         def myBid2 = new Bid(amount:145, buyer:buyer2, date:new Date(2011,3,4))
         def myBid3 = new Bid(amount:146, buyer:buyer2, date:new Date(2011,3,4))

        auctionListing.addToBids(myBid1)
        auctionListing.addToBids(myBid2)
        auctionListing.addToBids(myBid3)
        auctionListing.save()
        def foundAuctionByListing = Listing.findByListName('Jeep Grand Cherokee')
        assertEquals foundAuctionByListing.bids.size(), 3

        def foundBids = Bid.findAllByListing(foundAuctionByListing)
        assertEquals foundBids.asList().size(), 3
    }
}
